// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: fengyang

#include <cxxopts.hpp>
#include <google/protobuf/util/json_util.h>

#include "coin2/base/time.h"
#include "coin2/base/string_util.h"
#include "coin2/exchange/base/feed/rest/market_data_client.h"

using coin2::exchange::base::feed::rest::MarketDataClient;
using fastfeed::proto::KlineInterval;
using fastfeed::proto::KlineInterval_Parse;
using fastfeed::proto::TradingDataInterval;
using fastfeed::proto::TradingDataInterval_Parse;

int main(int argc, char* argv[]) {
  cxxopts::Options opt("Trading Feed Query", "Generate trading data");
  opt.add_options()
      ("mea", "MEA",
          cxxopts::value<std::string>())
      ("symbol", "norm symbol",
          cxxopts::value<std::string>())
      ("interval", "data interval",
          cxxopts::value<std::string>())
      ("start", "start time",
          cxxopts::value<std::string>())
      ("end", "end time",
          cxxopts::value<std::string>())
      ("type", "kline | top_account | top_position | global_account | taker | open_interest",
          cxxopts::value<std::string>()->default_value("kline"));

  auto res = opt.parse(argc, argv);
  MarketDataClient client;
  fastfeed::proto::Feed feed;
  std::string type = res["type"].as<std::string>();
  if (type == "kline") {
    std::string interval_arg = res["interval"].as<std::string>();
    std::string interval_name = "KLINE_INTERVAL_"
        + StringToUpperCopy(interval_arg);
    KlineInterval interval;
    CHECK(KlineInterval_Parse(interval_name, &interval))
        << "Invalid interval " << interval_arg;
    feed = client.QueryKlines(
        res["mea"].as<std::string>(),
        res["symbol"].as<std::string>(),
        interval,
        TimestampFromIso8601(res["start"].as<std::string>()),
        TimestampFromIso8601(res["end"].as<std::string>()));
  } else if (type == "top_account") {
    std::string interval_arg = res["interval"].as<std::string>();
    std::string interval_name = "TRADING_DATA_INTERVAL_"
        + StringToUpperCopy(interval_arg);
    TradingDataInterval interval;
    CHECK(TradingDataInterval_Parse(interval_name, &interval))
        << "Invalid interval " << interval_arg;
    feed = client.QueryTopLongShortAccountRatio(
        res["mea"].as<std::string>(),
        res["symbol"].as<std::string>(),
        interval,
        TimestampFromIso8601(res["start"].as<std::string>()),
        TimestampFromIso8601(res["end"].as<std::string>()));
  } else if (type == "top_position") {
    std::string interval_arg = res["interval"].as<std::string>();
    std::string interval_name = "TRADING_DATA_INTERVAL_"
        + StringToUpperCopy(interval_arg);
    TradingDataInterval interval;
    CHECK(TradingDataInterval_Parse(interval_name, &interval))
        << "Invalid interval " << interval_arg;
    feed = client.QueryTopLongShortPositionRatio(
        res["mea"].as<std::string>(),
        res["symbol"].as<std::string>(),
        interval,
        TimestampFromIso8601(res["start"].as<std::string>()),
        TimestampFromIso8601(res["end"].as<std::string>()));
  } else if (type == "global_account") {
    std::string interval_arg = res["interval"].as<std::string>();
    std::string interval_name = "TRADING_DATA_INTERVAL_"
        + StringToUpperCopy(interval_arg);
    TradingDataInterval interval;
    CHECK(TradingDataInterval_Parse(interval_name, &interval))
        << "Invalid interval " << interval_arg;
    feed = client.QueryGlobalLongShortAccountRatio(
        res["mea"].as<std::string>(),
        res["symbol"].as<std::string>(),
        interval,
        TimestampFromIso8601(res["start"].as<std::string>()),
        TimestampFromIso8601(res["end"].as<std::string>()));
  } else if (type == "taker") {
    std::string interval_arg = res["interval"].as<std::string>();
    std::string interval_name = "TRADING_DATA_INTERVAL_"
        + StringToUpperCopy(interval_arg);
    TradingDataInterval interval;
    CHECK(TradingDataInterval_Parse(interval_name, &interval))
        << "Invalid interval " << interval_arg;
    feed = client.QueryTakerBuySellRatio(
        res["mea"].as<std::string>(),
        res["symbol"].as<std::string>(),
        interval,
        TimestampFromIso8601(res["start"].as<std::string>()),
        TimestampFromIso8601(res["end"].as<std::string>()));
  } else if (type == "open_interest") {
    std::string interval_arg = res["interval"].as<std::string>();
    std::string interval_name = "TRADING_DATA_INTERVAL_"
        + StringToUpperCopy(interval_arg);
    TradingDataInterval interval;
    CHECK(TradingDataInterval_Parse(interval_name, &interval))
        << "Invalid interval " << interval_arg;
    feed = client.QueryOpenInterestHist(
        res["mea"].as<std::string>(),
        res["symbol"].as<std::string>(),
        interval,
        TimestampFromIso8601(res["start"].as<std::string>()),
        TimestampFromIso8601(res["end"].as<std::string>()));
  } else {
    THROW() << "Not support type " << type;
  }

  std::string buffer;
  google::protobuf::util::MessageToJsonString(feed, &buffer);
  std::cout << buffer << std::endl;

  return 0;
}

